home *** CD-ROM | disk | FTP | other *** search
/ CD/PC Actual 31 / PC Actual CD 31.iso / dists / SRC / SLIBEXEC.AA / SLIBEXEC / libexec / rbootd / parseconf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-24  |  9.7 KB  |  363 lines

  1. /*
  2.  * Copyright (c) 1988, 1992 The University of Utah and the Center
  3.  *    for Software Science (CSS).
  4.  * Copyright (c) 1992, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * the Center for Software Science of the University of Utah Computer
  9.  * Science Department.  CSS requests users of this software to return
  10.  * to css-dist@cs.utah.edu any improvements that they make and grant
  11.  * CSS redistribution rights.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  * 1. Redistributions of source code must retain the above copyright
  17.  *    notice, this list of conditions and the following disclaimer.
  18.  * 2. Redistributions in binary form must reproduce the above copyright
  19.  *    notice, this list of conditions and the following disclaimer in the
  20.  *    documentation and/or other materials provided with the distribution.
  21.  * 3. All advertising materials mentioning features or use of this software
  22.  *    must display the following acknowledgement:
  23.  *    This product includes software developed by the University of
  24.  *    California, Berkeley and its contributors.
  25.  * 4. Neither the name of the University nor the names of its contributors
  26.  *    may be used to endorse or promote products derived from this software
  27.  *    without specific prior written permission.
  28.  *
  29.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  30.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  33.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  38.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  39.  * SUCH DAMAGE.
  40.  *
  41.  *    from: @(#)parseconf.c    8.1 (Berkeley) 6/4/93
  42.  *
  43.  * From: Utah Hdr: parseconf.c 3.1 92/07/06
  44.  * Author: Jeff Forys, University of Utah CSS
  45.  */
  46.  
  47. #ifndef lint
  48. #if 0
  49. static const char sccsid[] = "@(#)parseconf.c    8.1 (Berkeley) 6/4/93";
  50. #endif
  51. static const char rcsid[] =
  52.     "$Id: parseconf.c,v 1.8 1997/11/24 07:33:40 charnier Exp $";
  53. #endif /* not lint */
  54.  
  55. #include <sys/param.h>
  56. #include <sys/stat.h>
  57.  
  58. #include <ctype.h>
  59. #include <dirent.h>
  60. #include <fcntl.h>
  61. #include <signal.h>
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <syslog.h>
  66. #include "defs.h"
  67.  
  68. /*
  69. **  ParseConfig -- parse the config file into linked list of clients.
  70. **
  71. **    Parameters:
  72. **        None.
  73. **
  74. **    Returns:
  75. **        1 on success, 0 otherwise.
  76. **
  77. **    Side Effects:
  78. **        - Linked list of clients will be (re)allocated.
  79. **
  80. **    Warnings:
  81. **        - GetBootFiles() must be called before this routine
  82. **          to create a linked list of default boot files.
  83. */
  84. int
  85. ParseConfig()
  86. {
  87.     FILE *fp;
  88.     CLIENT *client;
  89.     u_int8_t *addr;
  90.     char line[C_LINELEN];
  91.     char *cp, *bcp;
  92.     int i, j;
  93.     int omask, linecnt = 0;
  94.  
  95.     if (BootAny)                /* ignore config file */
  96.         return(1);
  97.  
  98.     FreeClients();                /* delete old list of clients */
  99.  
  100.     if ((fp = fopen(ConfigFile, "r")) == NULL) {
  101.         syslog(LOG_ERR, "ParseConfig: can't open config file (%s)",
  102.                ConfigFile);
  103.         return(0);
  104.     }
  105.  
  106.     /*
  107.      *  We've got to block SIGHUP to prevent reconfiguration while
  108.      *  dealing with the linked list of Clients.  This can be done
  109.      *  when actually linking the new client into the list, but
  110.      *  this could have unexpected results if the server was HUP'd
  111.      *  whilst reconfiguring.  Hence, it is done here.
  112.      */
  113.     omask = sigblock(sigmask(SIGHUP));
  114.  
  115.     /*
  116.      *  GETSTR positions `bcp' at the start of the current token,
  117.      *  and null terminates it.  `cp' is positioned at the start
  118.      *  of the next token.  spaces & commas are separators.
  119.      */
  120. #define GETSTR    while (isspace(*cp) || *cp == ',') cp++;    \
  121.         bcp = cp;                    \
  122.         while (*cp && *cp!=',' && !isspace(*cp)) cp++;    \
  123.         if (*cp) *cp++ = '\0'
  124.  
  125.     /*
  126.      *  For each line, parse it into a new CLIENT struct.
  127.      */
  128.     while (fgets(line, C_LINELEN, fp) != NULL) {
  129.         linecnt++;                /* line counter */
  130.  
  131.         if (*line == '\0' || *line == '#')    /* ignore comment */
  132.             continue;
  133.  
  134.         if ((cp = strchr(line,'#')) != NULL)    /* trash comments */
  135.             *cp = '\0';
  136.  
  137.         cp = line;                /* init `cp' */
  138.         GETSTR;                    /* get RMP addr */
  139.         if (bcp == cp)                /* all delimiters */
  140.             continue;
  141.  
  142.         /*
  143.          *  Get an RMP address from a string.  Abort on failure.
  144.          */
  145.         if ((addr = ParseAddr(bcp)) == NULL) {
  146.             syslog(LOG_ERR,
  147.                    "ParseConfig: line %d: cant parse <%s>",
  148.                    linecnt, bcp);
  149.             continue;
  150.         }
  151.  
  152.         if ((client = NewClient(addr)) == NULL)    /* alloc new client */
  153.             continue;
  154.  
  155.         GETSTR;                    /* get first file */
  156.  
  157.         /*
  158.          *  If no boot files are spec'd, use the default list.
  159.          *  Otherwise, validate each file (`bcp') against the
  160.          *  list of boot-able files.
  161.          */
  162.         i = 0;
  163.         if (bcp == cp)                /* no files spec'd */
  164.             for (; i < C_MAXFILE && BootFiles[i] != NULL; i++)
  165.                 client->files[i] = BootFiles[i];
  166.         else {
  167.             do {
  168.                 /*
  169.                  *  For each boot file spec'd, make sure it's
  170.                  *  in our list.  If so, include a pointer to
  171.                  *  it in the CLIENT's list of boot files.
  172.                  */
  173.                 for (j = 0; ; j++) {
  174.                     if (j==C_MAXFILE||BootFiles[j]==NULL) {
  175.                         syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)",
  176.                                linecnt, bcp);
  177.                         break;
  178.                     }
  179.                     if (STREQN(BootFiles[j], bcp)) {
  180.                         if (i < C_MAXFILE)
  181.                             client->files[i++] =
  182.                                 BootFiles[j];
  183.                         else
  184.                             syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)",
  185.                                    linecnt, bcp);
  186.                         break;
  187.                     }
  188.                 }
  189.                 GETSTR;            /* get next file */
  190.             } while (bcp != cp);
  191.  
  192.             /*
  193.              *  Restricted list of boot files were spec'd,
  194.              *  however, none of them were found.  Since we
  195.              *  apparently cant let them boot "just anything",
  196.              *  the entire record is invalidated.
  197.              */
  198.             if (i == 0) {
  199.                 FreeClient(client);
  200.                 continue;
  201.             }
  202.         }
  203.  
  204.         /*
  205.          *  Link this client into the linked list of clients.
  206.          *  SIGHUP has already been blocked.
  207.          */
  208.         if (Clients)
  209.             client->next = Clients;
  210.         Clients = client;
  211.     }
  212.  
  213.     (void) fclose(fp);                /* close config file */
  214.  
  215.     (void) sigsetmask(omask);            /* reset signal mask */
  216.  
  217.     return(1);                    /* return success */
  218. }
  219.  
  220. /*
  221. **  ParseAddr -- Parse a string containing an RMP address.
  222. **
  223. **    This routine is fairly liberal at parsing an RMP address.  The
  224. **    address must contain 6 octets consisting of between 0 and 2 hex
  225. **    chars (upper/lower case) separated by colons.  If two colons are
  226. **    together (e.g. "::", the octet between them is recorded as being
  227. **    zero.  Hence, the following addrs are all valid and parse to the
  228. **    same thing:
  229. **
  230. **        08:00:09:00:66:ad    8::9:0:66:AD    8::9::66:aD
  231. **
  232. **    For clarity, an RMP address is really an Ethernet address, but
  233. **    since the HP boot code uses IEEE 802.3, it's really an IEEE
  234. **    802.3 address.  Of course, all of these are identical.
  235. **
  236. **    Parameters:
  237. **        str - string representation of an RMP address.
  238. **
  239. **    Returns:
  240. **        pointer to a static array of RMP_ADDRLEN bytes.
  241. **
  242. **    Side Effects:
  243. **        None.
  244. **
  245. **    Warnings:
  246. **        - The return value points to a static buffer; it must
  247. **          be copied if it's to be saved.
  248. */
  249. u_int8_t *
  250. ParseAddr(str)
  251.     char *str;
  252. {
  253.     static u_int8_t addr[RMP_ADDRLEN];
  254.     char *cp;
  255.     unsigned i;
  256.     int part, subpart;
  257.  
  258.     memset((char *)&addr[0], 0, RMP_ADDRLEN);    /* zero static buffer */
  259.  
  260.     part = subpart = 0;
  261.     for (cp = str; *cp; cp++) {
  262.         /*
  263.          *  A colon (`:') must be used to delimit each octet.
  264.          */
  265.         if (*cp == ':') {
  266.             if (++part == RMP_ADDRLEN)    /* too many parts */
  267.                 return(NULL);
  268.             subpart = 0;
  269.             continue;
  270.         }
  271.  
  272.         /*
  273.          *  Convert hex character to an integer.
  274.          */
  275.         if (isdigit(*cp))
  276.             i = *cp - '0';
  277.         else {
  278.             i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10;
  279.             if (i < 10 || i > 15)        /* not a hex char */
  280.                 return(NULL);
  281.         }
  282.  
  283.         if (subpart++) {
  284.             if (subpart > 2)        /* too many hex chars */
  285.                 return(NULL);
  286.             addr[part] <<= 4;
  287.         }
  288.         addr[part] |= i;
  289.     }
  290.  
  291.     if (part != (RMP_ADDRLEN-1))            /* too few parts */
  292.         return(NULL);
  293.  
  294.     return(&addr[0]);
  295. }
  296.  
  297. /*
  298. **  GetBootFiles -- record list of files in current (boot) directory.
  299. **
  300. **    Parameters:
  301. **        None.
  302. **
  303. **    Returns:
  304. **        Number of boot files on success, 0 on failure.
  305. **
  306. **    Side Effects:
  307. **        Strings in `BootFiles' are freed/allocated.
  308. **
  309. **    Warnings:
  310. **        - After this routine is called, ParseConfig() must be
  311. **          called to re-order it's list of boot file pointers.
  312. */
  313. int
  314. GetBootFiles()
  315. {
  316.     DIR *dfd;
  317.     struct stat statb;
  318.     struct dirent *dp;
  319.     int i;
  320.  
  321.     /*
  322.      *  Free the current list of boot files.
  323.      */
  324.     for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) {
  325.         FreeStr(BootFiles[i]);
  326.         BootFiles[i] = NULL;
  327.     }
  328.  
  329.     /*
  330.      *  Open current directory to read boot file names.
  331.      */
  332.     if ((dfd = opendir(".")) == NULL) {    /* open BootDir */
  333.         syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n",
  334.                BootDir);
  335.         return(0);
  336.     }
  337.  
  338.     /*
  339.      *  Read each boot file name and allocate space for it in the
  340.      *  list of boot files (BootFiles).  All boot files read after
  341.      *  C_MAXFILE will be ignored.
  342.      */
  343.     i = 0;
  344.     for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) {
  345.         if (stat(dp->d_name, &statb) < 0 ||
  346.             (statb.st_mode & S_IFMT) != S_IFREG)
  347.             continue;
  348.         if (i == C_MAXFILE)
  349.             syslog(LOG_ERR,
  350.                    "GetBootFiles: too many boot files (%s ignored)",
  351.                    dp->d_name);
  352.         else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL)
  353.             i++;
  354.     }
  355.  
  356.     (void) closedir(dfd);            /* close BootDir */
  357.  
  358.     if (i == 0)                /* cant find any boot files */
  359.         syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir);
  360.  
  361.     return(i);
  362. }
  363.